#pragma once

#include "util.hpp"
#include <unordered_map>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

//在线用户管理，主要是对当前游戏大厅和游戏房间中的用户进行管理，主要得建立起用户与SOCKET连接得映射关系
//功能：可以通过用户信息：id找到能够与用户客户端进行通信的socket连接。
//判断一个用户是否在线。
typedef websocketpp::server<websocketpp::config::asio> wsserver_t;  //websocketpp的连接

class online_manger
{
public:
    //进入游戏厅的客户端进行连接
    void enter_game_hall(int uid, const wsserver_t::connection_ptr& conn)
    {
        DLOG("%d 用户被添加到游戏大厅中", uid);
        unique_lock<mutex> lock(_mutex);
        _game_hall.insert(make_pair(uid, conn));
    }

    //退出游戏厅的客户端进行连接
    void exit_game_hall(int uid)
    {
        DLOG("%d 用户退出游戏大厅", uid);
        unique_lock<mutex> lock(_mutex);
        _game_hall.erase(uid);
    }

     //进入游戏房间的客户端进行连接
    void enter_room_hall(int uid, const wsserver_t::connection_ptr& conn)
    {
        unique_lock<mutex> lock(_mutex);
        _room_hall.insert(make_pair(uid, conn));
    }

    //退出游戏房间的客户端进行连接
    void exit_room_hall(int uid)
    {
        unique_lock<mutex> lock(_mutex);
        _room_hall.erase(uid);
    }

    //判断该用户是否在游戏大厅
    bool in_game_hall(int uid)
    {
        unique_lock<mutex> lock(_mutex);
        if(_game_hall.find(uid) == _game_hall.end())
        {
            DLOG("%d 用户不在大厅中", uid);
            return false;
        }
        return true;
    }

    //判断该用户是否在游戏房间
    bool in_room_hall(int uid)
    {
        unique_lock<mutex> lock(_mutex);
        if(_room_hall.find(uid) == _room_hall.end())
        {
            return false;
        }
        return true;
    }


    //根据用户id从游戏大厅中获取其对应的socket连接
    bool get_conn_from_game_id(int uid, wsserver_t::connection_ptr& conn)
    {
        unique_lock<mutex> lock(_mutex);
        auto it = _game_hall.find(uid);
        if(it == _game_hall.end())
        {
            return false;
        }
        conn = it->second;
        return true;
     }

     //根据用户id从游戏房间中获取其对应的socket连接
    bool get_conn_from_room_id(int uid, wsserver_t::connection_ptr& conn)
    {
        unique_lock<mutex> lock(_mutex);
        auto it = _room_hall.find(uid);
        if(it == _room_hall.end())
        {
            return false;
        }
        conn = it->second;
        return true;
     }
     
private:
    //游戏大厅的客户端连接管理
    unordered_map<int, wsserver_t::connection_ptr> _game_hall;
    //游戏房间的客户端连接管理
    unordered_map<int, wsserver_t::connection_ptr> _room_hall;
    //在对数据进行管理时保证其原子性。因为STL控件不较于MYSQL接口均不保证原子性，所以需要手动的维护其原子性。
    mutex _mutex;
};